package com.iwhalecloud.uncc.service.impl;

import com.iwhalecloud.uncc.common.ArchiverConstant;
import com.iwhalecloud.uncc.common.ArchiverThreadLocal;
import com.iwhalecloud.uncc.common.SysConstant;
import com.iwhalecloud.uncc.dao.ArchiverDao;
import com.iwhalecloud.uncc.db.DatasourceContextHolder;
import com.iwhalecloud.uncc.domain.InsCollectTaskArchiverMsg;
import com.iwhalecloud.uncc.exception.ArchiverException;
import com.iwhalecloud.uncc.model.*;
import com.iwhalecloud.uncc.properties.mq.ArchiverTopicProperties;
import com.iwhalecloud.uncc.service.ArchiverService;
import com.iwhalecloud.uncc.utils.ArchiverUtil;
import com.iwhalecloud.uncc.utils.CheckUtil;
import com.iwhalecloud.uncc.utils.DivideUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author zq
 * @date 2021/10/15 15:29
 * @description InsCollectTaskArchiverServiceImpl
 */
@Slf4j
@Service("insCollectTaskArchiverService")
public class InsCollectTaskArchiverServiceImpl implements ArchiverService<InsCollectTask> {

    @Autowired
    private ArchiverDao insCollectTaskArchiverDao;
    @Autowired
    private ArchiverDao insCollectTaskBatchArchiverDao;
    @Autowired
    private ArchiverDao insDataLogArchiverDao;
    @Autowired
    private ArchiverDao insDistributeFileLogArchiverDao;
    @Autowired
    private ArchiverDao insHttpCmdLogArchiverDao;
    @Autowired
    private ArchiverDao insTaskFileLogArchiverDao;
    @Autowired
    private ArchiverDao insTacheRecordArchiverDao;
    @Autowired
    private ArchiverDao insTacheInstArchiverDao;
    @Autowired
    private ArchiverDao insTacheLogArchiverDao;
    @Autowired
    private ArchiverDao collectVirCommandInstArchiverDao;
    @Autowired
    private ArchiverDao collectCommandInstArchiverDao;
    @Autowired
    private ArchiverDao insEventRecordArchiverDao;
    @Autowired
    private ArchiverTopicProperties archiverTopicProperties;

    @Async("taskExecutor")
    @Override
    public void archive(String partitionCode) {
        DatasourceContextHolder.setDs(partitionCode);
        this.doArchive();
        DatasourceContextHolder.setDs(SysConstant.DB_DEFAULT_PARTITION);
    }

    private void doArchive() {
        long s = System.currentTimeMillis();
        if (log.isInfoEnabled()) {
            log.info(Thread.currentThread().getName() + "执行归档 "
                    + DatasourceContextHolder.getDs() + "数据库 InsCollectTask 关联数据发送任务 ..." );
        }

        List<InsCollectTask> list = insCollectTaskArchiverDao.queryList(null);

        if(list == null){
            if (log.isInfoEnabled()) {
                log.info("此次任务InsCollectTaskList = null");
                log.info(Thread.currentThread().getName() + "完成任务:NULL耗时:"
                        + ((System.currentTimeMillis() - s) / 1000) + "s");
            }
            return;
        }
        //list 不为 null;
        DivideUtil.divideSend(this,list);

        if (log.isInfoEnabled()) {
            log.info(Thread.currentThread().getName() + "完成归档发送任务,条数:"
                    + list.size() + "耗时:" + ((System.currentTimeMillis() - s) / 1000) + "s");
        }
    }

    /**
     * packMsg
     * @param list
     * @return
     */
    @Override
    public void packMsg(List<InsCollectTask> list) {

        //修改 Flag
        CheckUtil.batchUpdateArchiving(insCollectTaskArchiverDao,list);

        List<Long> taskIds = new ArrayList<>();
        list.forEach(i->taskIds.add(i.getId()));

        List<String> batchNos = new ArrayList<>();
        list.forEach(i->batchNos.add(i.getBatchNo()));

        List<InsCollectTaskBatch> insCollectTaskBatchList = CheckUtil.batchQuery(insCollectTaskBatchArchiverDao,batchNos);

        //修改 Flag
        CheckUtil.batchUpdateArchiving(insCollectTaskBatchArchiverDao,insCollectTaskBatchList);

        List<InsEventRecord>  insEventRecordList = CheckUtil.batchQuery(insEventRecordArchiverDao,taskIds);
        insEventRecordList = CheckUtil.dealInsEventRecord(insEventRecordList,
                CheckUtil.batchQuery(insEventRecordArchiverDao,batchNos));

        List<InsDataLog> insDataLogList =  CheckUtil.batchQuery(insDataLogArchiverDao,taskIds);

        List<InsDistributeFileLog> insDistributeFileLogList = CheckUtil.batchQuery(insDistributeFileLogArchiverDao,taskIds);

        List<InsHttpCmdLog> insHttpCmdLogList = CheckUtil.batchQuery(insHttpCmdLogArchiverDao,taskIds);

        List<InsTaskFileLog> insTaskFileLogList = CheckUtil.batchQuery(insTaskFileLogArchiverDao,taskIds);

        List<InsTacheRecord> insTacheRecordList = CheckUtil.batchQuery(insTacheRecordArchiverDao,taskIds);

        List<InsTacheInst> insTacheInstList = CheckUtil.batchQuery(insTacheInstArchiverDao,taskIds);
        List<InsTacheLog> insTacheLogList = null;
        if(insTacheInstList != null){
            List<Long> tacheInstIds = new ArrayList<>();
            insTacheInstList.forEach(i->tacheInstIds.add(i.getId()));
            insTacheLogList = CheckUtil.batchQuery(insTacheLogArchiverDao,tacheInstIds);
            insEventRecordList = CheckUtil.dealInsEventRecord(insEventRecordList,
                    CheckUtil.batchQuery(insEventRecordArchiverDao,tacheInstIds));
        }

        //修改 Flag
        if(insEventRecordList != null) {
            //distinct
            insEventRecordList = insEventRecordList.stream().distinct().collect(Collectors.toList());
            CheckUtil.batchUpdateArchiving(insEventRecordArchiverDao,insEventRecordList);
        }

        List<CollectVirCommandInst> collectVirCommandInstList = CheckUtil.batchQuery(collectVirCommandInstArchiverDao,taskIds);
        List<CollectCommandInst> collectCommandInstList = null;
        if(collectVirCommandInstList != null){
            List<Long> instIds = new ArrayList<>();
            collectVirCommandInstList.forEach(i->instIds.add(i.getInstId()));
            collectCommandInstList = CheckUtil.batchQuery(collectCommandInstArchiverDao,instIds);
        }

        //Msg
        InsCollectTaskArchiverMsg insCollectTaskArchiverMsg = new InsCollectTaskArchiverMsg();
        insCollectTaskArchiverMsg.setIsDeleteOnline(ArchiverThreadLocal.getArchiveParam().getIsDeleteOnline());
        insCollectTaskArchiverMsg.setPartitionCode(DatasourceContextHolder.getDs());
        insCollectTaskArchiverMsg.setInsCollectTaskBatchList(insCollectTaskBatchList);
        insCollectTaskArchiverMsg.setInsCollectTaskList(list);
        insCollectTaskArchiverMsg.setInsDataLogList(insDataLogList);
        insCollectTaskArchiverMsg.setInsDistributeFileLogList(insDistributeFileLogList);
        insCollectTaskArchiverMsg.setInsHttpCmdLogList(insHttpCmdLogList);
        insCollectTaskArchiverMsg.setInsTaskFileLogList(insTaskFileLogList);
        insCollectTaskArchiverMsg.setInsTacheRecordList(insTacheRecordList);
        insCollectTaskArchiverMsg.setInsTacheInstList(insTacheInstList);
        insCollectTaskArchiverMsg.setInsTacheLogList(insTacheLogList);
        insCollectTaskArchiverMsg.setCollectVirCommandInstList(collectVirCommandInstList);
        insCollectTaskArchiverMsg.setCollectCommandInstList(collectCommandInstList);
        insCollectTaskArchiverMsg.setInsEventRecordList(insEventRecordList);

//        ClassLayoutUtil.printMsg(insCollectTaskArchiverMsg);

        try{
            sendMsg(insCollectTaskArchiverMsg);
        }catch (ArchiverException a){
            if (log.isInfoEnabled()) {
                log.info(Thread.currentThread().getName() + a.getErrorMessage());
            }
            //重置 Flag
            CheckUtil.batchResetOnline(insCollectTaskArchiverDao,list);
            CheckUtil.batchResetOnline(insCollectTaskBatchArchiverDao,insCollectTaskBatchList);
            CheckUtil.batchResetOnline(insEventRecordArchiverDao,insEventRecordList);

            a.printStackTrace();
        }
    }

    /**
     * sendMsg
     * @param msg
     */
    private void sendMsg(InsCollectTaskArchiverMsg msg) throws ArchiverException {
        String key = ArchiverConstant.PREFIX_INS_COLLECT_TASK + msg.getInsCollectTaskList().get(0).getId();
        String topic = archiverTopicProperties.getInsCollectTaskArchiverTopic();
        ArchiverUtil.sendMsg(topic,key,msg);
    }

}
